Imports System.Runtime.Serialization
Imports System.Runtime.Versioning
''' <summary>
''' This class defines BikiRom MegaBoard Settings to be saved within the CarBase Class
''' </summary>
''' <remarks></remarks>

<Serializable()> Friend Class BikSettings

    Friend Enum funcCode As Byte
        BF_NONE = 0
        BF_BOOST = &H10
        BF_PID = &H11
        BF_GENERLAL_PWM = &H20
        BF_GENERAL_ON_OFF = &H21
        BF_TURBO_TIMER = &H30
        BF_NOTSET = &HFF
    End Enum
    Friend Enum TableVariables As Byte
        BCTV_RPM = &H0
        BCTV_AFM = &H1
        BCTV_TPS = &H2
        BCTV_MAP = &H3
        BCTV_TEMP = &H4
        BCTV_SPEED = &H5
        BCTV_BKI1 = &H20
        BCTV_BKI2 = &H21
        BCTV_BKI3 = &H22
        BCTV_BKI4 = &H23
        BCTV_BKI5 = &H24
        BCTV_BKAD1 = &H25
        BCTV_BKAD2 = &H26
        BCTV_BKAD3 = &H27
        BCTV_TRIG1 = &H30
        BCTV_TRIG2 = &H31
        BCTV_TRIG3 = &H32
        BCTV_TRIG4 = &H33
        BCTV_TRIG5 = &H34
        BCTV_TRIG6 = &H35
        BCTV_TRIG7 = &H36
        BCTV_TRIG8 = &H37
        BCTV_TRIG9 = &H38
        BCTV_TRIG10 = &H39
        BCTV_TRIG11 = &H3A
        BCTV_TRIG12 = &H3B
        BCTV_TRIG13 = &H3C
        BCTV_TRIG14 = &H3D
        BCTV_TRIG15 = &H3E
        BCTV_TRIG16 = &H3F
        BCTV_TRIG17 = &H40
        BCTV_TRIG18 = &H41
        BCTV_TRIG19 = &H42
        BCTV_TRIG20 = &H43
        BCTV_BKADLU1 = &H60
        BCTV_BKADLU2 = &H61
        BCTV_BKADLU3 = &H62
        BCTV_UNDEFINED = &HFF
        BCTV_AL1 = &H70
        BCTV_AL2 = &H71
        BCTV_AL3 = &H72
        BCTV_AL4 = &H73
        BCTV_AL5 = &H74
        BCTV_AL6 = &H75
        BCTV_AL7 = &H76
        BCTV_AL8 = &H77
        BCTV_AL9 = &H78
        BCTV_AL10 = &H79
        BCTV_AL11 = &H7A
        BCTV_AL12 = &H7B
        BCTV_AL13 = &H7C
        BCTV_AL14 = &H7D
        BCTV_AL15 = &H7E
        BCTV_AL16 = &H7F
        BCTV_AL17 = &H80
        BCTV_AL18 = &H81
        BCTV_AL19 = &H82
        BCTV_AL20 = &H83
        BCTV_AL21 = &H84
        BCTV_AL22 = &H85
        BCTV_AL23 = &H86
        BCTV_AL24 = &H87
        BCTV_AL25 = &H88
        BCTV_AL26 = &H89
        BCTV_AL27 = &H8A
        BCTV_AL28 = &H8B
        BCTV_AL29 = &H8C
        BCTV_AL30 = &H8D
        BCTV_AL31 = &H8E
        BCTV_AL32 = &H8F
    End Enum
    Friend Enum TableTypes As Byte
        BCTT_TRIMPER = &H0
        BCTT_TRIMVAL = &H1
        BCTT_BASE = &H2
        BCTT_ONOFF = &H3
        BCTT_MAPCHANGE = &H4
        BCTT_UNDEFINED = &HFF
    End Enum
    Friend Enum BK_ioID As UShort
        BK_IO_NONE = 14
        BK_IO_SW1 = 0
        BK_IO_SW2 = 1
        BK_IO_SW3 = 2
        BK_IO_SW4 = 3
        BK_IO_SW5 = 4
        BK_IO_OUT1 = 10
        BK_IO_OUT2 = 11
        BK_IO_OUT3 = 12
        BK_IO_OUT4 = 13
        BK_TRIG = &H20
        BK_OUT = &H30
        BK_CONSULT = &H40
        BK_ADLOOKUPs = &H50
        BK_DAC = &H60
    End Enum

    '' Constants
    <OptionalField(VersionAdded:=3)> _
    Friend Const EEPROM_VERSION_ADR As Long = &H68F
    <OptionalField(VersionAdded:=2)> _
    Friend Const nAuFirstByte As Long = &HA10
    <OptionalField(VersionAdded:=2)> _
    Friend Const nTrigFirstByte As ULong = &H400
    <OptionalField(VersionAdded:=2)> _
    Friend Const nAUCount As UInt16 = 64
    <OptionalField(VersionAdded:=2)> _
    Friend Const nAUbytesPerUnit As UInt16 = 9
    <OptionalField(VersionAdded:=2)> _
    Friend Const nTrigCount As UInt16 = 20

    Private m_data() As Byte = Nothing
    Private m_table As Table = Nothing
    Private m_firstNode As SubConfig = Nothing
    Private m_enabled As Byte = 0

    Sub New(ByRef Vars As BVars)
        'm_firstNode = New SubConfig()
        ReDim m_data(&HCFF)
        For i As Integer = 0 To m_data.Length - 1
            m_data(i) = &HFF
        Next
        CreateSettings(Vars)
    End Sub
    Friend Sub addNode(ByRef config As SubConfig)
        If Not IsNothing(config) Then If IsNothing(m_firstNode) Then m_firstNode = config Else m_firstNode.addNode(config)
    End Sub

    Private Sub CreateSettings(ByRef Vars As BVars)
        'Try
        Dim f_work As SubConfig
        ' Get the new data size for the eeprom shit

        m_firstNode = Nothing

        Me.addNode(New SubConfig(m_data, 0, BK_ioID.BK_CONSULT, 0, Vars))
        Me.addNode(New SubConfig(m_data, 0, BK_ioID.BK_ADLOOKUPs, 0, Vars))
        Me.addNode(New SubConfig(m_data, 0, BK_ioID.BK_DAC, 0, Vars))

        f_work = New SubConfig
        f_work.Name = "seperator"
        Me.addNode(f_work)

        Me.addNode(New SubConfig(m_data, &H0, BK_ioID.BK_OUT, 1, Vars))
        Me.addNode(New SubConfig(m_data, &H100, BK_ioID.BK_OUT, 2, Vars))
        Me.addNode(New SubConfig(m_data, &H200, BK_ioID.BK_OUT, 3, Vars))
        Me.addNode(New SubConfig(m_data, &H300, BK_ioID.BK_OUT, 4, Vars))

        f_work = New SubConfig
        f_work.Name = "seperator"
        Me.addNode(f_work)

        Me.addNode(New SubConfig(m_data, &H400, BK_ioID.BK_TRIG, 1, Vars))
        Me.addNode(New SubConfig(m_data, &H410, BK_ioID.BK_TRIG, 2, Vars))
        Me.addNode(New SubConfig(m_data, &H420, BK_ioID.BK_TRIG, 3, Vars))
        Me.addNode(New SubConfig(m_data, &H430, BK_ioID.BK_TRIG, 4, Vars))
        Me.addNode(New SubConfig(m_data, &H440, BK_ioID.BK_TRIG, 5, Vars))
        Me.addNode(New SubConfig(m_data, &H450, BK_ioID.BK_TRIG, 6, Vars))
        Me.addNode(New SubConfig(m_data, &H460, BK_ioID.BK_TRIG, 7, Vars))
        Me.addNode(New SubConfig(m_data, &H470, BK_ioID.BK_TRIG, 8, Vars))
        Me.addNode(New SubConfig(m_data, &H480, BK_ioID.BK_TRIG, 9, Vars))
        Me.addNode(New SubConfig(m_data, &H490, BK_ioID.BK_TRIG, 10, Vars))
        Me.addNode(New SubConfig(m_data, &H4A0, BK_ioID.BK_TRIG, 11, Vars))
        Me.addNode(New SubConfig(m_data, &H4B0, BK_ioID.BK_TRIG, 12, Vars))
        Me.addNode(New SubConfig(m_data, &H4C0, BK_ioID.BK_TRIG, 13, Vars))
        Me.addNode(New SubConfig(m_data, &H4D0, BK_ioID.BK_TRIG, 14, Vars))
        Me.addNode(New SubConfig(m_data, &H4E0, BK_ioID.BK_TRIG, 15, Vars))
        Me.addNode(New SubConfig(m_data, &H4F0, BK_ioID.BK_TRIG, 16, Vars))
        Me.addNode(New SubConfig(m_data, &H500, BK_ioID.BK_TRIG, 17, Vars))
        Me.addNode(New SubConfig(m_data, &H510, BK_ioID.BK_TRIG, 18, Vars))
        Me.addNode(New SubConfig(m_data, &H520, BK_ioID.BK_TRIG, 19, Vars))
        Me.addNode(New SubConfig(m_data, &H530, BK_ioID.BK_TRIG, 20, Vars))
        'Catch
        '    Err_message("Error creating bikirom config")
        '    Err_report(Err.Description)
        'End Try
    End Sub
    Friend Sub ClearSetting(ByRef Vars As BVars)

        ' Update the array!
        If UBound(m_data) <> &HCFF Then
            Dim f_Length As Integer = m_data.Length
            ReDim Preserve m_data(&HCFF)
            For i As Integer = f_Length To m_data.Length - 1
                m_data(i) = &HFF
            Next
        End If

        If Not IsNothing(Vars) Then
            Dim f_var As BVar = Vars.getByName("EEProm_Layout")
            If Not IsNothing(f_var) Then
                translateLayout(f_var.Value)
                f_var.Value = My.Settings.Firmware_MemLayout

            Else
                translateLayout(0)
                Vars.addNode(New BVar("EEProm_Layout", New BikDescription("eeprom memory layout"), My.Settings.Firmware_MemLayout))
            End If
        End If
        'Try
        If IsNothing(m_firstNode) Then
            CreateSettings(Vars)
        Else
            For Each item As SubConfig In Me.getConfigsAsArray
                item.Refresh(m_data)
            Next
        End If
        'Catch
        '    Err_message("Error re-generating bikirom config")
        'End Try
    End Sub
    ''' <summary>
    ''' Updates the eeprom memory layout and gets it up to the new specification
    ''' </summary>
    ''' <param name="Version"></param>
    ''' <remarks></remarks>
    Private Function translateLayout(ByVal Version As Double) As Boolean

        ' Update to Memory Layout 1.0
        If Version < 1.0! And (m_data(EEPROM_VERSION_ADR) < &H10 Or m_data(EEPROM_VERSION_ADR) = &HFF) Then
            ' Clean up the Auxilary Ouputs
            Dim f_data(&H54F) As Byte
            Dim f_offset, f_tableOffset As UInt16
            For i As Integer = 0 To f_data.Length - 1
                f_data(i) = &HFF
            Next
            f_data(0) = m_data(0)
            f_data(&HFF) = m_data(&HFF)
            f_data(&H100) = m_data(&H100)
            f_data(&H200) = m_data(&H200)
            f_data(&H2FF) = m_data(&H2FF)
            f_data(&H300) = m_data(&H300)

            For a As Short = 0 To 3
                f_offset = (a * &H100) + 1
                For o As Short = 0 To 9
                    f_tableOffset = f_offset + (o * 28)
                    Array.Copy(m_data, f_offset + (o * 23), f_data, f_tableOffset, 23)

                    Select Case (CType(f_data(f_tableOffset), TableTypes))
                        Case TableTypes.BCTT_ONOFF
                            f_data(f_tableOffset + 2) = f_data(f_tableOffset + 6)
                            Array.Copy(System.BitConverter.GetBytes(CSng((CUShort(f_data(f_tableOffset + 7)) << 8 Or (f_data(f_tableOffset + 8))))), 0, f_data, f_tableOffset + 3, 4)
                            f_data(f_tableOffset + 7) = f_data(f_tableOffset + 9)
                            Array.Copy(System.BitConverter.GetBytes(CSng((CUShort(f_data(f_tableOffset + 10)) << 8 Or (f_data(f_tableOffset + 11))))), 0, f_data, f_tableOffset + 8, 4)
                        Case TableTypes.BCTT_BASE, TableTypes.BCTT_TRIMPER, TableTypes.BCTT_TRIMVAL
                            Array.Copy(System.BitConverter.GetBytes(CSng((CUShort(f_data(f_tableOffset + 4)) << 8 Or (f_data(f_tableOffset + 5))))), 0, f_data, f_tableOffset + 23, 4)
                            Array.Copy(System.BitConverter.GetBytes(CSng((CUShort(f_data(f_tableOffset + 2)) << 8 Or (f_data(f_tableOffset + 3))))), 0, f_data, f_tableOffset + 2, 4)
                    End Select
                Next
            Next

            ' Clean up the Triggers
            For a As Short = 0 To 19
                f_offset = (a * 16) + &H400
                Array.Copy(m_data, f_offset, f_data, f_offset, 16)
                f_data(f_offset + 4) = f_data(f_offset + 8)
                Array.Copy(System.BitConverter.GetBytes(CSng((CUShort(f_data(f_offset + 9)) << 8 Or (f_data(f_offset + 10))))), 0, f_data, f_offset + 5, 4)
                f_data(f_offset + 9) = f_data(f_offset + 11)
                Array.Copy(System.BitConverter.GetBytes(CSng((CUShort(f_data(f_offset + 12)) << 8 Or (f_data(f_offset + 13))))), 0, f_data, f_offset + 10, 4)
            Next

            ' Copy back the translated settings :)
            Array.Copy(f_data, 0, m_data, 0, &H550)

            m_data(EEPROM_VERSION_ADR) = &H10
        End If
        ' Update to Verion 1.1!
        If Version < 1.1! And (m_data(EEPROM_VERSION_ADR) < &H11 Or m_data(EEPROM_VERSION_ADR) = &HFF) Then
            ' Convert the First Aux Output Hz calc location
            If m_data(&HFF) > 0 And m_data(&HFE) <> &HFF Then
                Select Case m_data(&HFF)
                    Case 1
                        System.BitConverter.GetBytes(CSng(20)).CopyTo(m_data, &HFC)
                    Case 2
                        System.BitConverter.GetBytes(CSng(81)).CopyTo(m_data, &HFC)
                    Case 3
                        System.BitConverter.GetBytes(CSng(325)).CopyTo(m_data, &HFC)
                    Case 4
                        System.BitConverter.GetBytes(CSng(2600)).CopyTo(m_data, &HFC)
                    Case 5
                        System.BitConverter.GetBytes(CSng(20800)).CopyTo(m_data, &HFC)
                    Case Else
                        System.BitConverter.GetBytes(CSng(0)).CopyTo(m_data, &HFC)
                End Select
            Else
                 System.BitConverter.GetBytes(CSng(0)).CopyTo(m_data, &HFC)
            End If

            ' Convert the Thrid Aux output Hz calc location
            If m_data(&H2FF) > 0 And m_data(&H2FF) <> &HFF Then
                Select Case m_data(&H2FF)
                    Case 1
                        System.BitConverter.GetBytes(CSng(20)).CopyTo(m_data, &H2FC)
                    Case 2
                        System.BitConverter.GetBytes(CSng(81)).CopyTo(m_data, &H2FC)
                    Case 3
                        System.BitConverter.GetBytes(CSng(325)).CopyTo(m_data, &H2FC)
                    Case 4
                        System.BitConverter.GetBytes(CSng(2600)).CopyTo(m_data, &H2FC)
                    Case 5
                        System.BitConverter.GetBytes(CSng(20800)).CopyTo(m_data, &H2FC)
                    Case Else
                        System.BitConverter.GetBytes(CSng(0)).CopyTo(m_data, &H2FC)
                End Select
            Else
               System.BitConverter.GetBytes(CSng(0)).CopyTo(m_data, &H2FC)
            End If

            m_data(EEPROM_VERSION_ADR) = &H11
        End If

        Return True
    End Function

    Shared Function TableVariableName(ByVal Value As TableVariables) As String
        Select Case Value
            Case TableVariables.BCTV_AFM
                Return "AFM"
            Case TableVariables.BCTV_BKAD1
                Return "AD1"
            Case TableVariables.BCTV_BKAD2
                Return "AD2"
            Case TableVariables.BCTV_BKAD3
                Return "AD3"
            Case TableVariables.BCTV_BKI1
                Return "SW1"
            Case TableVariables.BCTV_BKI2
                Return "SW2"
            Case TableVariables.BCTV_BKI3
                Return "SW3"
            Case TableVariables.BCTV_BKI4
                Return "SW4"
            Case TableVariables.BCTV_BKI5
                Return "SW5"
            Case TableVariables.BCTV_RPM
                Return "RPM"
            Case TableVariables.BCTV_SPEED
                Return "SPEED"
            Case TableVariables.BCTV_TEMP
                Return "TEMP"
            Case TableVariables.BCTV_TPS
                Return "TPS"
            Case TableVariables.BCTV_BKADLU1
                Return "ADCLU1"
            Case TableVariables.BCTV_BKADLU2
                Return "ADCLU2"
            Case TableVariables.BCTV_BKADLU3
                Return "ADCLU3"
        End Select

        If Value >= TableVariables.BCTV_TRIG1 And Value <= TableVariables.BCTV_TRIG20 Then
            Return "TR" & Value - &H2F
        End If

        Return ""
    End Function
    Shared Function TableVariableTrace(ByVal Value As TableVariables) As traceScheme
        Select Case Value
            Case BikSettings.TableVariables.BCTV_AFM
                Return traceScheme.TRC_AFM
            Case BikSettings.TableVariables.BCTV_BKAD1
                Return traceScheme.TRC_AD1
            Case BikSettings.TableVariables.BCTV_BKAD2
                Return traceScheme.TRC_AD2
            Case BikSettings.TableVariables.BCTV_BKAD3
                Return traceScheme.TRC_AD3
            Case BikSettings.TableVariables.BCTV_BKI1
                Return traceScheme.TRC_BI1
            Case BikSettings.TableVariables.BCTV_BKI2
                Return traceScheme.TRC_BI2
            Case BikSettings.TableVariables.BCTV_BKI3
                Return traceScheme.TRC_BI3
            Case BikSettings.TableVariables.BCTV_BKI4
                Return traceScheme.TRC_BI4
            Case BikSettings.TableVariables.BCTV_BKI5
                Return traceScheme.TRC_BI5
            Case BikSettings.TableVariables.BCTV_MAP
                Return traceScheme.TRC_MAP
            Case BikSettings.TableVariables.BCTV_TPS
                Return traceScheme.TRC_TPS
            Case BikSettings.TableVariables.BCTV_TEMP
                Return traceScheme.TRC_TEMP
            Case BikSettings.TableVariables.BCTV_SPEED
                Return traceScheme.TRC_SPD
            Case BikSettings.TableVariables.BCTV_RPM
                Return traceScheme.TRC_RPM
            Case TableVariables.BCTV_BKADLU1
                Return traceScheme.TRC_ADLU1
            Case TableVariables.BCTV_BKADLU2
                Return traceScheme.TRC_ADLU2
            Case TableVariables.BCTV_BKADLU3
                Return traceScheme.TRC_ADLU3
            Case Else
                Return traceScheme.TRC_NONE
        End Select
    End Function
    Shared Function TableVariableMult(ByVal value As TableVariables) As Double
        Select Case value
            Case TableVariables.BCTV_AFM, TableVariables.BCTV_BKAD1, _
                TableVariables.BCTV_BKAD3, TableVariables.BCTV_BKAD2
                Return 5
            Case TableVariables.BCTV_RPM
                Return 12.5
            Case TableVariables.BCTV_SPEED
                Return 2
            Case TableVariables.BCTV_TPS
                Return 20
            Case Else
                Return 1
        End Select
    End Function
    Shared Function TableVariableOffset(ByVal value As TableVariables) As Double
        Select Case value
            Case TableVariables.BCTV_TEMP
                Return -50
            Case Else
                Return 0
        End Select
    End Function

    Public Property Data() As Byte()
        Get
            Return m_data
        End Get
        Set(ByVal value As Byte())
            m_data = value
        End Set
    End Property
    Public Property Enabled() As Byte
        Get
            Return m_enabled
        End Get
        Set(ByVal value As Byte)
            m_enabled = value
        End Set
    End Property
    Friend Function getTable() As Table
        Return m_table
    End Function
    Friend Function getData() As Byte()
        Return m_data
    End Function
    Friend Function getSettings() As SubConfig
        Return m_firstNode
    End Function
    Friend Function DownloadSettings() As Boolean
        Dim f_read() As Byte = Nothing
        If BikiRom_Init() = BK_return.BK_OK Then
            BikiRom_SetTimeout(4000)
            f_read = BikiRom_DownloadWcmd("CC9300", 2)
            BikiRom_SetTimeout(200)
        End If
        If Not IsNothing(f_read) Then m_data = f_read : Return True Else Return False
    End Function
    Friend Sub setForSave()
        m_firstNode = Nothing
    End Sub
    Friend Sub setForUpload()
        setForSave()
        m_data = Nothing
    End Sub

    Friend Function count() As Integer
        Dim f_return As Integer = 0
        If Not IsNothing(m_firstNode) Then
            f_return += m_firstNode.count
        End If
        Return f_return
    End Function
    Friend Function getConfigsAsArray() As SubConfig()
        Dim f_return() As SubConfig = Nothing
        If Me.count >= 1 Then
            ReDim f_return(Me.count - 1)
            For i As Int16 = 0 To Me.count - 1
                f_return(i) = Me.getByIndex(i)
            Next
        End If
        Return f_return
    End Function
    Friend Function getByID(ByVal ID As BK_ioID) As SubConfig
        Dim f_configs() As SubConfig = Me.getConfigsAsArray
        For Each subc As SubConfig In f_configs
            If subc.ID = ID Then Return subc
        Next
        Return Nothing
    End Function
    Friend Function getByIndex(ByVal Index_ As Integer) As SubConfig
        Dim f_cursor As SubConfig
        Dim found As Boolean = False
        If Not IsNothing(m_firstNode) Then
            f_cursor = m_firstNode
            If Index_ = 0 Then
                Return f_cursor
                found = True
            Else
                For count As Integer = 1 To Index_
                    If Not IsNothing(f_cursor.getNext) Then
                        f_cursor = f_cursor.getNext
                        found = True
                    Else
                        Return Nothing
                        Exit For
                    End If
                Next
            End If
        Else
            Return Nothing
        End If
        If found = False Then Return Nothing Else Return f_cursor
    End Function
End Class
